运维之道 - 后端
type: channel
link: https://blog.tianhao.tech/{category}/backend/
items: MongoDB 高可用副本集终极部署教程
items: Hadoop之HDFS详解
items: MySQL 事务日志(redo log和undo log
items: MySQL 地基基础
items: MySQL 主从复制
items: OLTP和OLAP对比哪个更好用？二者有什么区别？

MongoDB 高可用副本集终极部署教程
type: item
date: 2025-11-08T16:25:00+08:00
description: —— AlmaLinux 9 + TLS 单向认证 + 账号密码认证版（适用于生产环境，2025 最新实践）只要求服务器 TLS 证书、客户端仅需用户名密码登录集群拓扑节点角色主机名IP 地址操作系统PRIMARYmongo1192.168.6.111AlmaLinux 9SECONDARYmongo2192.168.6.112AlmaLinux 9SECONDARYmongo3192.168.6.113AlmaLinux 9副本集名称：test1MongoDB 版本：8.2.x认证方式：用户名 + 密码（SCRAM-SHA-256）加密通信：TLS 单向认证（仅服务端证书）🧩 阶段 0：基础环境准备（所有节点执行）1️⃣ 添加 MongoDB Yum 源sudo tee /etc/yum.repos.d/mongodb-org-8.2.repo <<EOF [mongodb-org-8.2] name=MongoDB Repository baseurl=https://repo.mongodb.org/yum/redhat/9/mongodb-org/8.2/x86_64/ gpgcheck=1 enabled=1 gpgkey=https://pgp.mongodb.com/server-8.0.asc EOF2️⃣ 安装 MongoDBsudo dnf remove -y mongodb-org* # 如有旧版本先卸载 sudo dnf clean all sudo dnf install -y mongodb-org3️⃣ 配置主机名解析编辑 /etc/hosts：192.168.6.111 mongo1 192.168.6.112 mongo2 192.168.6.113 mongo34️⃣ 创建证书存放目录sudo mkdir -p /etc/mongodb/pki sudo chown -R mongod:mongod /etc/mongodb/pki sudo chmod 700 /etc/mongodb/pki5️⃣ 防火墙与 SELinux 设置sudo firewall-cmd --zone=public --add-port=27017/tcp --permanent sudo firewall-cmd --reload sudo setenforce 0 sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config🧩 阶段 1：生成与分发安全凭证（仅在 mongo1 执行）1️⃣ 生成内部认证 KeyFilesudo openssl rand -base64 756 > /etc/mongodb/pki/mongodb.key sudo chmod 400 /etc/mongodb/pki/mongodb.key sudo chown mongod:mongod /etc/mongodb/pki/mongodb.key2️⃣ 创建 TLS 服务端证书（CA + Server）cd /etc/mongodb/pki # 创建 CA 根证书 openssl genrsa -out ca.key 4096 openssl req -x509 -new -key ca.key -days 3650 -out root.pem -subj "/C=CN/ST=Beijing/L=Beijing/O=TianhaoTech/CN=MongoCA" # 创建服务器证书 openssl genrsa -out server.key 4096 openssl req -new -key server.key -out server.csr -subj "/C=CN/ST=Beijing/L=Beijing/O=TianhaoTech/CN=mongodb-cluster" openssl x509 -req -in server.csr -CA root.pem -CAkey ca.key -CAcreateserial -out server.crt -days 3650 -extensions v3_req \ -extfile <(printf "[v3_req]\nsubjectAltName=DNS:mongo1,DNS:mongo2,DNS:mongo3,IP:192.168.6.111,IP:192.168.6.112,IP:192.168.6.113") # 合并为 PEM cat server.key server.crt > server.pem # 设置权限 sudo chown mongod:mongod…

Hadoop之HDFS详解
type: item
date: 2025-06-13T15:36:00+08:00
description: HDFS介绍我们前面已经知道了HDFS是一个分布式的文件系统，具体这个分布式文件系统是如何实现的呢？我们来举个例子分析一下。小明租房：小明同学呢，今年是大四，需要离校去实习了，出去实习首要解决的是住宿的问题，目前软件行业很少包住宿的，反正我是没听说过，但是小明呢，有一个特点，就是懒，还穷，天天出去住酒店肯定是住不起的，那只能租房了，租房呢他还不想自己去找房子，嫌麻烦，所以就随便在路边找了一个二房东贴的广告，单间出租，拎包入住，无中介费，押一付一，一月300，小明一看，可以，还不错，所以就直接打电话过去看房子办手续了，这样就解决了住宿的问题。紧接着小明的同学看他这么快就搞定了住宿问题，房租也挺便宜，都问他要二房东的电话，小明就把二房东的电话发到了他们的年级群里，上千人啊，结果二房东的手机就被打爆了，最后只能关机了，人太多了，实在搞不定了。因为目前有租房需求的学员太多了，全部都去找这一个二房东，他是搞不定的，因为他每天带看的人数是有限的。那这个时候怎么办呢？小明同学还是比较热心的，发现二房东解决不了这么大的需求，然后他正发愁呢，结果一抬头看到了一个中介公司，小明露出了满嘴的大白牙。然后他就顺利搞到了这个中介公司的电话，赶紧把这个电话发到了年级群里面，这个时候，当再有学员有租房需求的时候，直接打中介公司的电话，然后中介公司会让具体的工作人员直接联系这个学员，负责他的租房需求，每一个工作人员最多负责5个人，因为中介公司里面是有很多工作人员的，这样一分流，就很轻松的解决了这个问题。这个时候针对中介公司而言，它只负责管理房源和工作人员就行了，具体干活的是工作人员。这样就算同时过来很多人，中介公司也是可以扛得住的，因为具体看房租房的流程是直接和工作人员对接的，不会造成阻塞。ok 这就是小明租房的一个案例，那这个案例和我们要讲的HDFS有什么关系呢？不要着急，我们来往下面看。假设让我们来设计一个分布式的文件系统，我们该如何设计呢？看这个图片，用户在写入数据和读取数据的时候会通过一个文件系统，这个文件系统后面会有很多台服务器，所以我们的数据就可以存储在多台服务器上面。后期服务器增加或者减少，对我们用户而言，不用关注，这个统一由文件系统进行管理，我们只需要和文件系统进行交互就可以了。这样是不是就实现了分布式存储了，这种方案在实际应用中可行吗？在这里就可以把文件系统理解为二房东，服务器理解为房子，这种设计架构会存在一个问题，假设同时过来很多人都需要租房子，那么一个二房东是忙不过来的，就会造成阻塞。那继续往下面看[]()现在这种设计是，我们去找一个中介公司，这里的主节点就可以理解为一个中介公司这里的从节点就可以理解为是房源，中介公司会在每块房源都安排一个工作人员，当我们找房子的时候，先联系中介公司，中介公司会告诉我们哪里有房子，并且把对应工作人员的信息告诉我们，我们就可以直接去找对应的工作人员去租房子。这样对于中介公司而言，就没什么压力了。中介公司只负责管理房源和工作人员信息，具体干活的是工作人员。这样就算同时过来很多人，中介公司也是可以扛得住的，因为具体看房租房的流程是我们直接和工作人员联系的，不会造成阻塞。所以对应到我们的分布式存储设计上面：用户请求查看数据时候会请求主节点，主节点上面会维护所有数据的存储信息，主节点会把对应数据所在的节点信息返回给用户，然后用户根据数据所在的节点信息去对应的节点去读取数据，这样压力就不会全部在主节点上面。这个就是HDFS这个分布式文件系统的设计思想。HDFS(Hadoop Distributed File System)HDFS的全称是Hadoop Distributed File System ，Hadoop的 分布式 文件 系统它是一种允许文件通过网络在多台主机上分享的文件系统，可以让多台机器上的多个用户分享文件和存储空间其实分布式文件管理系统有很多，HDFS只是其中一种实现而已还有 GFS(谷歌的)、TFS(淘宝的)、S3(亚马逊的)为什么会有多种分布式文件系统呢？这样不是重复造轮子吗？不是的，因为不同的分布式文件系统的特点是不一样的，HDFS是一种适合大文件存储的分布式文件系统，不适合小文件存储，什么叫小文件，例如，几KB，几M的文件都可以认为是小文件HDFS的Shell介绍通过前面的学习，我们对HDFS有了基本的了解，下面我们就想实际操作一下，来通过实操加深对HDFS的理解针对HDFS，我们可以在shell命令行下进行操作，就类似于我们操作linux中的文件系统一样，但是具体命令的操作格式是有一些区别的格式如下：使用hadoop bin目录的hdfs命令，后面指定dfs，表示是操作分布式文件系统的，这些属于固定格式。如果在PATH中配置了hadoop的bin目录，那么这里可以直接使用hdfs就可以了这里…

MySQL 事务日志(redo log和undo log
type: item
date: 2025-06-11T16:11:27+08:00
description: MySQL 事务日志(redo log和undo log)innodb事务日志包括redo log和undo log。redo log是重做日志，提供前滚操作，undo log是回滚日志，提供回滚操作。undo log不是redo log的逆向过程，其实它们都算是用来恢复的日志： 1.redo log通常是物理日志，记录的是数据页的物理修改，而不是某一行或某几行修改成怎样怎样，它用来恢复提交后的物理数据页(恢复数据页，且只能恢复到最后一次提交的位置)。 2.undo用来回滚行记录到某个版本。undo log一般是逻辑日志，根据每行记录进行记录。1.redo log1.1 redo log和二进制日志的区别二进制日志相关内容，参考：。redo log不是二进制日志。虽然二进制日志中也记录了innodb表的很多操作，也能实现重做的功能，但是它们之间有很大区别。二进制日志是在存储引擎的上层产生的，不管是什么存储引擎，对数据库进行了修改都会产生二进制日志。而redo log是innodb层产生的，只记录该存储引擎中表的修改。并且二进制日志先于redo log被记录。具体的见后文group commit小结。二进制日志记录操作的方法是逻辑性的语句。即便它是基于行格式的记录方式，其本质也还是逻辑的SQL设置，如该行记录的每列的值是多少。而redo log是在物理格式上的日志，它记录的是数据库中每个页的修改。二进制日志只在每次事务提交的时候一次性写入缓存中的日志”文件”(对于非事务表的操作，则是每次执行语句成功后就直接写入)。而redo log在数据准备修改前写入缓存中的redo log中，然后才对缓存中的数据执行修改操作；而且保证在发出事务提交指令时，先向缓存中的redo log写入日志，写入完成后才执行提交动作。因为二进制日志只在提交的时候一次性写入，所以二进制日志中的记录方式和提交顺序有关，且一次提交对应一次记录。而redo log中是记录的物理页的修改，redo log文件中同一个事务可能多次记录，最后一个提交的事务记录会覆盖所有未提交的事务记录。例如事务T1，可能在redo log中记录了 T1-1,T1-2,T1-3，T1 共4个操作，其中 T1 表示最后提交时的日志记录，所以对应的数据页最终状态是 T1* 对应的操作结果。而且redo log是并发写入的，不同事务之间的不同版本的记录会穿插写入到redo log文件中，例如可能redo log的记录方式如下： T1-1,T1-2,T2-1,T2-2,T2。事务日志记录的是物理页的情况，它具有幂等性，因此记录日志的方式极其简练。幂等性的意思是多次操作前后状态是一样的，例如新插入一行后又删除该行，前后状态没有变化。而二进制日志记录的是所有影响数据的操作，记录的内容较多。例如插入一行记录一次，删除该行又记录一次。1.2 redo log的基本概念redo log包括两部分：一是内存中的日志缓冲(redo log buffer)，该部分日志是易失性的；二是磁盘上的重做日志文件(redo log file)，该部分日志是持久的。在概念上，innodb通过force log at commit机制实现事务的持久性，即在事务提交的时候，必须先将该事务的所有事务日志写入到磁盘上的redo log file和undo log file中进行持久化。为了确保每次日志都能写入到事务日志文件中，在每次将log buffer中的日志写入日志文件的过程中都会调用一次操作系统的fsync操作(即fsync()系统调用)。因为MariaDB/MySQL是工作在用户空间的，MariaDB/MySQL的log buffer处于用户空间的内存中。要写入到磁盘上的log file中(redo:ib_logfileN文件,undo:share tablespace或.ibd文件)，中间还要经过操作系统内核空间的os buffer，调用fsync()的作用就是将OS buffer中的日志刷到磁盘上的log file中。也就是说，从redo log buffer写日志到磁盘的redo log file中，过程如下：在此处需要注意一点，一般所说的log file并不是磁盘上的物理日志文件，而是操作系统缓存中的log file，官方手册上的意思也是如此(例如：With a value of 2, the contents of the InnoDB log buffer are written to the log file after each transaction commit and the log file is flushed to disk approximately once per second)。但说实话，…

MySQL 地基基础
type: item
date: 2025-06-11T16:08:00+08:00
description: MySQL 地基基础：事务和锁的面纱什么是事务，为什么需要事务在 MySQL 中，事务是由一条或多条 SQL 组成的单位，在这个单位中所有的 SQL 共存亡，有点有福同享，有难同当的意思。要么全部成功，事务顺利完成；要么只要有一个 SQL 失败就会导致整个事务失败，所有已经做过的操作回退到原始数据状态。用日常细说事务的特性首先我们先说一下事务的四个特性：ACID。A：原子性（atomicity），一个事务要么全都成功，要么全都失败C：一致性（consistency），在事务的整个生命周期里，查询的数据是一致的，保证数据库不会返回未提交的事务的数据I：隔离性（isolation），一个事务所做的操作，在最终提交前，对其他事务是不可见的，保证事务与事务之间不会冲突D：持久性（durability），只要事务提交，数据就不会丢失，即使系统崩溃，事务也已经完成在日常生活中有很多的事情就能体现为数据库中的事务。比如“转账”，下面我们就具体展开，你就可以很清晰的认识事务的四个特性。时间：2020 年 1 月 1 日地点：某银行 ATM人物：A 和 B起因：B 向 A 借 1000 元人民币经过：A 转账给 B结果：转账成功或失败这么一个转账我们想一下底层基本的技术支撑与实现，B 向 A 借钱，A 要转账给 B，首先 A 必须有大于 1000 元的余额，然后从 A 的账户减 1000 元，在 B 的账户里加 1000 元。我们定义一个事务：获取 A 账户余额 select balance from account where username='A'; 在 A 账户里减 1000 元 update account set balance=balance-1000 where username='A'; 获取 B 账户余额 select balance from account where username='B'; 在 B 账户里加 1000 元 update account set balance=balance+1000 where username='B';好了，一个简单事务基本就这样，我们开始分析分析这个事务是如何保证事务的 ACID 的。原子性：这个事务要么全成功，要么全失败。事务成功则 1000 元转账到了 B 账户，事务失败回滚则 1000 元还在 A 账户里，就是说 1000 元不能凭空消失。一致性：在这个事务中，所有的查询都是一致的，我们先查询 A 账户余额是否大于 1000，如果小于 1000，事务失败回滚；如果获取不到 B 账户余额，事务失败回滚。隔离性：在这个事务发生的同时，发生了另一个事务（A 通过手机银行将钱全部转移到另外的账户，比如一共有 1500 元），第一个事务转 1000 元，第二个事务转 1500 元，我们仔细想想，如果都成功，那岂不是凭空获取了 1000 元，这是不合理的，每个事务在执行前都应查一下余额是否够本次转账的。这两个事务应该是隔离的，不能有冲突。持久性：转账成功了（即事务完成），这代表钱已经发生了转移，这个时候发生 ATM 吞卡、ATM 断电、手机银行无法登陆等等一切故障，反正钱已经转走了，钱没有丢（即数据没有丢）MySQL 并发控制技术并发控制技术可以说是数据库的底层基础技术，并发控制技术可以拆分来看，一是并发，一是控制。并发也就是说大量请求连接到数据库，控制就是数据库要控制好这些连接，保证资源的可用性、安全性，解决资源的挣用的问题。那么如何实现并控制呢？主要通过两个方面：LockMVCC先分别简单说一下 Lock 和 MVCC，具体的后面再聊。Lock，并发连接到数据库，操作有读和读、读和写、写和写，锁来保证并发连接使得数据可以保持一致性。MVCC（Multiversion Concurrency Control），多版本并发控制，是数据库的多版本，可以提高并发过程中的读和写操作，有效的避免写请求阻塞读请求。面试再也不怕被问到的 MVCC前面我们已经大致了解了 MVCC 是什么，以及他做什么事情，现在我们具体看看 MVCC 是如何工作的？我们知道数据的一致性，可以通过锁来保证，在并发连接中，锁机制在读和读的并发请求中不会锁数据，但是在读和写的并发请求中，写请求会加锁，读请求会被写请求阻塞，基于此，MVCC 发挥其作用。MVCC 控制两类操作：快照读：读取的是历史可见版本的数据，无锁当前读：读取的是当前最新版本的数据，加锁我们举个例子说一下吧，比如:mysql> create table tab1(id decimal,name varchar(10),address varchar(10),status decimal,primary key(id)); mysql> insert in…

MySQL 主从复制
type: item
date: 2025-06-11T16:01:49+08:00
description: MySQL 主从复制本文非常详细地介绍MySQL复制相关的内容，包括基本概念、复制原理、如何配置不同类型的复制(传统复制)等等。在此文章之后，还有几篇文章分别介绍GTID复制、半同步复制、实现MySQL的动静分离，以及MySQL 5.7.17引入的革命性功能：组复制(MGR)。本文是MySQL Replication的基础，但却非常重要。对于MySQL复制，如何搭建它不是重点(因为简单，网上资源非常多)，如何维护它才是重点(网上资源不集中)。以下几个知识点是掌握MySQL复制所必备的：复制的原理将master上已存在的数据恢复到slave上作为基准数据获取正确的binlog坐标深入理解show slave status中的一些状态信息本文对以上内容都做了非常详细的说明。希望对各位初学、深入MySQL复制有所帮助。mysql replication官方手册：1.复制的基本概念和原理mysql复制是指从一个mysql服务器(MASTER)将数据通过日志的方式经过网络传送到另一台或多台mysql服务器(SLAVE)，然后在slave上重放(replay或redo)传送过来的日志，以达到和master数据同步的目的。它的工作原理很简单。首先确保master数据库上开启了二进制日志，这是复制的前提。在slave准备开始复制时，首先要执行change master to语句设置连接到master服务器的连接参数，在执行该语句的时候要提供一些信息，包括如何连接和要从哪复制binlog，这些信息在连接的时候会记录到slave的datadir下的master.info文件中，以后再连接master的时候将不用再提供这新信息而是直接读取该文件进行连接。在slave上有两种线程，在slave准备开始复制时，首先要执行change master to语句设置连接到master服务器的连接参数，在执行该语句的时候要提供一些信息，包括如何连接和要从哪复制binlog，这些信息在连接的时候会记录到slave的datadir下的master.info文件中，以后再连接master的时候将不用再提供这新信息而是直接读取该文件进行连接。在slave上有两种线程，分别是IO线程和SQL线程IO线程用于连接master，监控和接受master的binlog。当启动IO线程成功连接master时，master会同时启动一个dump线程，该线程将slave请求要复制的binlog给dump出来，之后IO线程负责监控并接收master上dump出来的二进制日志，当master上binlog有变化的时候，IO线程就将其复制过来并写入到自己的中继日志(relay log)文件中。slave上的另一个线程SQL线程用于监控、读取并重放relay log中的日志，将数据写入到自己的数据库中。如下图所示。站在slave的角度上看，过程如下：站在master的角度上看，过程如下(默认的异步复制模式，前提是设置了sync_binlog=1，否则binlog刷盘时间由操作系统决定)：所以，可以认为复制大致有三个步骤：数据修改写入master数据库的binlog中。slave的IO线程复制这些变动的binlog到自己的relay log中。slave的SQL线程读取并重新应用relay log到自己的数据库上，让其和master数据库保持一致。从复制的机制上可以知道，在复制进行前，slave上必须具有master上部分完整内容作为复制基准数据。例如，master上有数据库A，二进制日志已经写到了pos1位置，那么在复制进行前，slave上必须要有数据库A，且如果要从pos1位置开始复制的话，还必须有和master上pos1之前完全一致的数据。如果不满足这样的一致性条件，那么在replay中继日志的时候将不知道如何进行应用而导致数据混乱。也就是说，复制是基于binlog的position进行的，复制之前必须保证position一致。(注：这是传统的复制方式所要求的)可以选择对哪些数据库甚至数据库中的哪些表进行复制。默认情况下，MySQL的复制是异步的。slave可以不用一直连着master，即使中间断开了也能从断开的position处继续进行复制。MySQL 5.6对比MySQL 5.5在复制上进行了很大的改进，主要包括支持GTID(Global Transaction ID,全局事务ID)复制和多SQL线程并行重放。GTID的复制方式和传统的复制方式不一样，通过全局事务ID，它不要求复制前slave有基准数据，也不要求binlog的position一致。MySQL 5.7.17则提出了组复制(MySQL Group Replication,MGR)的概念。像数据库这样的产品，必须要尽可能完…

OLTP和OLAP对比哪个更好用？二者有什么区别？
type: item
date: 2025-06-10T13:55:00+08:00
description: OLTP概念操作型处理，叫联机事务处理OLTP(On-LineTransactionProcessing)，主要目标是做数据处理，它是针对具体业务在数据库联机的日常操作，通常对少数记录进行查询、修改。用户较为关心操作的响应时间、数据的安全性、完整性和并发支持的用户数等问题。传统的关系型数据库系统(RDBMS)作为数据管理的主要手段，主要用于操作型处理。OLAP概念分析型处理，叫联机分析处理OLAP(On-Line Analytical Processing)，主要目标是做数据分析。一般针对某些主题的历史数据进行复杂的多维分析，支持管理决策。数据仓库是OLAP系统的一个典型示例，主要用于数据分析。OLTP、OLAP对比OLTP是联机事务处理，OLAP是联机分析处理，相较来说还是有很多大差别的，具体可以参照下表：OLAP引擎分类OLAP按存储器的数据存储格式分为MOLAP(Multi-dimensional OLAP) 、ROLAP(Relational OLAP)和 HOLAP(Hybrid OLAP)。MOLAP，基于多维数组的存储模型，也是OLAP最初的形态，特点是对数据进行预计算，以空间换效率，明细和聚合数据都保存在cube中。但生成cube需要大量时间和空间。MOLAP可选Kylin、Druid等开源产品。ROLAP，完全基于关系模型进行存储数据，不需要预计算，按需即时查询。明细和汇总数据都保存在关系型数据库事实表中。HOLAP，混合模型，细节数据以ROLAP存放，聚合数据以MOLAP存放。这种方式相对灵活，且更加高效。开源的OLAP引擎有以下几类，可以看到Doris拥有众多优点，运维成本低，兼容Mysql访问协议等等，在变化维、非预设维、细粒度统计的应用场景下，使用MPP引擎驱动的ROLAP模式，可以简化模型设计，减少预计算的代价，并通过强大的实时计算能力，可以支撑良好的实时交互体验。doris是一个ROLAP引擎, 可以满足：灵活多维分析、明细+聚合、主键更新。